﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.CodeCompletion;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Highlighting;

namespace EffectEd.HlslEditor
{
    /// <summary>
    /// Interaction logic for HlslEdit.xaml
    /// </summary>
    public partial class HlslEdit : UserControl
    {

        private bool _ctrlDown;

        private CompletionWindow _completionWindow;

        public HlslEdit()
        {
            InitializeComponent();
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            ShowLineNumbers = true;
            lineNumberMargin.Opacity = 0.3;
            textEditor.TextArea.LeftMargins.Add(lineNumberMargin);

            textEditor.PreviewKeyDown += textEditor_PreviewKeyDown;
            textEditor.PreviewKeyUp += textEditor_PreviewKeyUp;
            textEditor.TextChanged += TextEditorOnTextChanged;
        }

        private void TextEditorOnTextChanged(object sender, EventArgs e)
        {
            if (TextChanged != null) TextChanged(this, EventArgs.Empty);
        }

        /// <summary>
        /// Shows completion window for passed functions.
        /// </summary>
        public void ShowCompletionWindow(CodeCompletionSettings settings)
        {
            if (settings.CompletionData == null || !settings.CompletionData.Any()) return;
            _completionWindow = new CompletionWindow(textEditor.TextArea);
            ICompletionData first = null;
            foreach (var item in settings.CompletionData)
            {
                if (first == null) first = item;
                _completionWindow.CompletionList.CompletionData.Add(item);
            }
            _completionWindow.StartOffset = settings.IdentifierSegment.Offset;
            _completionWindow.EndOffset = settings.IdentifierSegment.EndOffset;

            if (first != null)
            {
                _completionWindow.CompletionList.SelectedItem = first;
            }
            _completionWindow.Show();
            _completionWindow.Closed += (sender, args) => _completionWindow = null;
            _completionWindow.PreviewTextInput += (sender, args) =>
            {
                if (args.Text == "(" || args.Text == " ")
                {
                    _completionWindow.CompletionList.RequestInsertion(EventArgs.Empty);
                }
                var c = args.Text[args.Text.Length - 1];
                args.Handled = !char.IsLetterOrDigit(c) && c != '_';
            };
        }

        public void SelectWordAt(int row, int column)
        {
            if (string.IsNullOrWhiteSpace(textEditor.Text)) return;
            textEditor.TextArea.Caret.Line = row;
            textEditor.TextArea.Caret.Column = column;
            var offset = textEditor.TextArea.Caret.Offset;

            var ch = textEditor.Text[offset];
            var index = 1;
            while (char.IsLetterOrDigit(ch) || ch == '_')
            {
                ch = textEditor.Text[offset + index++];
            }
            index = Math.Max(1, index - 1);

            textEditor.TextArea.Selection = new SimpleSelection(offset, offset + index);
            textEditor.TextArea.Caret.Offset = offset + index;
            textEditor.Focus();
            textEditor.TextArea.Caret.BringCaretToView();
        }

        private void textEditor_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.LeftCtrl)
            {
                _ctrlDown = true;
            }
            if (e.Key == Key.Space && _ctrlDown)
            {
                if (CodeCompletionProvider != null)
                {
                    ShowCompletionWindow(CodeCompletionProvider.GetCompletion(textEditor.Text, textEditor.CaretOffset));
                    e.Handled = true;
                }
            }

        }

        private void textEditor_PreviewKeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.LeftCtrl)
            {
                _ctrlDown = false;
            }
        }

        /// <summary>
        /// The source code in the editor.
        /// </summary>
        public string Text
        {
            get { return textEditor.Text; }
            set { textEditor.Text = value; }
        }

        public IHighlightingDefinition SyntaxHighlighting
        {
            get
            {
                return textEditor.SyntaxHighlighting;
            }
            set { textEditor.SyntaxHighlighting = value; }
        }

        public ICodeCompletionProvider CodeCompletionProvider { get; set; }

        public EventHandler TextChanged;

        public TextEditor TextEditor { get { return textEditor; } }

        public LineNumberMargin LineNumberMargin { get { return lineNumberMargin; }}

        public TextArea TextArea
        {
            get { return textEditor.TextArea; }
        }

        private bool _showLineNumbers;
        public bool ShowLineNumbers
        {
            get { return _showLineNumbers; }
            set
            {
                _showLineNumbers = value;
                lineNumberMargin.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
            }
        }

        
    }
}
